#!/usr/bin/ksh

#########################################################################
#									#
# Name:		mkpkg.autopackage (Shell script)			#
#									#
# Completed:	7th June, 2005.						#
#									#
# Updated:	27th September, 2005.					#
#									#
# Author:	Simon Edwards.						#
#									#
# Arguments:	-V		Print codemgr packaging type - 		#
#				currently set to 1.			#
#									#
# Arguments:	-r rel [-x cfg] [-v] [-f]				#
#		-r		Indicate the number of the release to	#
#				create - assigned by the 		#
#				mkpkg wrapper script usually.		#
#		-x		Specify an alternative cfg file - 	#
#				the default will be "cfg".		#
#		-f		Force create - if a version of this	#
#				release already exists it should be	#
#				over-written.				#
#									#
# Purpose:	This creates takes the information for the current	#
#		project and creates an autopackage package for it. 	#
#		It does this using the information taken from the 	#
#		RELMGR_CONF file and also the configuration file 	#
#		used for packing itself - found typically in the 	#
#		pkg/cfg file.						#
#									#
#		This script does not check that all source code is	#
#		checked it - that is the business of the mkpkg wrapper	#
#		script.							#
#									#
#		The program is run where $PWD is the complete		#
#		code directory. We will need to create an autopackage	#
#		directory, and then create a default.apspec file in it.	#
#									#
# Limitations:	1 - Initial attempt at using autopackage, so quality	#
#		    of packages is not expected to be high.		#
#									#
# Environment:	RELMGR_CFG	- Defines the file name containing the	#
#				  configuration settings for the 	#
#				  release manager for this user.	#
#									#
# Exit Codes:	0  - Package created successfully / all files in 	#
#		     version control system.				#
#		>1 - An error has occurred / not all files under 	#
#		     version control are checked back in.		#
# 									#
#########################################################################

function logmsg
{
	[[ $ARG_verbose -eq 0 ]] && return
	print "MSG  : $1"
}

function logwarn
{
	print "WARN : $1"
}

function logerr
{
	print -u2 "ERROR: $1"
	[[ -n "$2" ]] && exit $2
}

SCRIPT=$(basename $0)
function loadvar 
{
	#################################################################
	# If we do not currently have a pkg directory, then create one!	#
	#################################################################

	[[ ! -d $1/pkg ]] && {
		mkdir -p $1/pkg 2>/dev/null || {
			logerr "Unable to create pkg directory" 2;
		}
		logwarn "Pkg directory auto-created!";
	}

	#################################################################
	# We also need to do the same thing for the autopackage		#
	# directory.							#
	#################################################################

	[[ ! -d $1/autopackage ]] && {
		mkdir -p $1/autopackage 2>/dev/null || {
			logerr "Unable to create autopackage directory" 2;
		}
	}

	[[ ! -f $1/pkg/$CFGFILE ]] && {
		logerr "Configuration file \"$1/pkg/$CFGFILE\" does not exist." 5;
	}
	if [[ -n "$3" && "$3" = m ]]
	then
		( . $1/pkg/$CFGFILE 2>/dev/null; eval print \$$2 )
	elif [[ -n "$3" && "$3" = s ]]
	then
		awk -v searchfor="$2" '$1 == "#" {next} $1 ~ searchfor {split($0,a,"="); if(substr(a[1],1,length(searchfor)) == searchfor) { printf("%s %s\n",a[1],a[2]);exit(0);}}' \
		$1/pkg/$CFGFILE
	else
		awk -v searchfor="$2" '$1 == "#" {next} $1 ~ searchfor {split($0,a,"="); if(substr(a[1],1,length(searchfor)) == searchfor) { printf("%s %s\n",a[1],a[2]);}}' \
		$1/pkg/$CFGFILE
	fi
	return 0
}

function usage
{
	print -u2 "Usage: $SCRIPT -r release [-f] [-v]

Written by Simon Edwards (C) 2005.
Please see the codemgr_$SCRIPT(1) manual page for more details.
"
exit 1
}

[[ -z "$RELMGR_CFG" ]] && {
	logerr "Variable \"RELMGR_CFG\" is not defined." 10;
}

[[ ! -f "$RELMGR_CFG" ]] && {
	logerr "\"RELMGR_CFG\" setting ($RELMGR_CFG) is not valid." 11;
}

whoami=$(whoami)

#########################################################################
# Now source the configuration information...				#
#########################################################################

. $RELMGR_CFG

export PROJECT_PREFIX PROJECT_PKGDIR PROJECT_RELDB PKG_TYPE VCTYPE
export DEFAULT_GROUP DEFAULT_PERMS DEFAULT_OWNER IGNORE_SUFFIXES
export FINAL_DEPOT

#########################################################################
# If the wrapper has been to generate the package it will have set the	#
# BUILD_IN_TMP variable, which now becomes the PROJECT_PREFIX for this	#
# particular package build.						#
#########################################################################

if [[ -n "$BUILD_IN_TMP" && -d $BUILD_IN_TMP ]]
then
	logmsg "PROJECT_PREFIX modified to $BUILD_IN_TMP"
	PROJECT_PREFIX=$BUILD_IN_TMP
fi

#########################################################################
# Now we have the basic details we need to parse the command line	#
# arguments to ensure everything looks ok.				#
#########################################################################

VERSION=0
FORCE=0
RELEASE=""
ARG_verbose=0
CFGFILE=""

while getopts ":Vfvr:x:" argval
do
	case $argval in
		V)	VERSION=1		;;
		f)	FORCE=1			;;
		v)	ARG_verbose=1		;;
		x)	CFGFILE=$OPTARG		;;
		r)	RELEASE=$OPTARG		;;
		*)	usage
	esac
done

if [[ $VERSION = 1 ]]
then
	print 1
	exit 0
fi

[[ -z "$CFGFILE" ]] && CFGFILE=cfg
[[ -z "$RELEASE" ]] && usage

#########################################################################
# We now work out the current product name, using the current directory	#
# path as a starting point. If the current directory path is not	#
# path of the PROJECT_PREFIX then we need to raise an error.		#
#########################################################################

project_name=$(print $PWD|
	awk -v projs=$PROJECT_PREFIX '{if(substr($1,1,length(projs))!=projs) exit(0);
		split(substr($1,2+length(projs)),a,"/");
		print a[1];}')

if [[ -z "$project_name" ]]
then
	logerr "Current path is invalid for a project!"
	logerr "Path must be sub-directory of \"$PROJECT_PREFIX\"." 12
fi

logmsg "Project name ascertained to be: $project_name"
pkg_url=$(loadvar $PROJECT_PREFIX/$project_name URL|awk '{print $2}')
pkg_name=$(loadvar $PROJECT_PREFIX/$project_name NAME|awk '{print $2}')
pkg_desc=$(loadvar $PROJECT_PREFIX/$project_name DESCRIPTION s|awk '{for(n=2; n<=NF; n++) printf("%s ",$n);}')
pkg_ldesc=$(loadvar $PROJECT_PREFIX/$project_name DESCRIPTION m|awk '{for(n=2; n<=NF; n++) printf("%s ",$n);}')
pkg_license=$(loadvar $PROJECT_PREFIX/$project_name LICENSE s|awk '{for(n=2; n<=NF; n++) printf("%s ",$n);}')
pkg_buildscript=$(loadvar $PROJECT_PREFIX/$project_name BUILDSCRIPT s|awk '{print $2}')
pkg_ignore_suffixes=$(loadvar $PROJECT_PREFIX/$project_name IGNORE_SUFFIXES s|awk '{print $2}' | sed 's/"//g')
pkg_relative=$(loadvar $PROJECT_PREFIX/$project_name AUTOPACKAGE:PKG_RELATIVE s|awk '{print toupper($2)}')

if [[ -z "$pkg_relative" || "$pkg_relative" != "YES" ]]
then
	pkg_relative="NO"
fi
[[ -z "$pkg_url" ]] && pkg_url="$(hostname)/"

#########################################################################
# A lot of these probably are not relevant to autopackage, but get	#
# details anyway...							#
#########################################################################

pkg_preinstall=$(loadvar $PROJECT_PREFIX/$project_name PREINSTALL|awk '{print $2}')
pkg_postinstall=$(loadvar $PROJECT_PREFIX/$project_name POSTINSTALL|awk '{print $2}')
pkg_checkinstall=$(loadvar $PROJECT_PREFIX/$project_name CHECKINSTALL|awk '{print $2}')
pkg_preremove=$(loadvar $PROJECT_PREFIX/$project_name PREREMOVE|awk '{print $2}')
pkg_postremove=$(loadvar $PROJECT_PREFIX/$project_name POSTREMOVE|awk '{print $2}')

if [[ -z "$pkg_ignore_suffixes" && -n "$IGNORE_SUFFIXES" ]]
then
pkg_ignore_suffixes="$IGNORE_SUFFIXES"
logmsg "Ignored suffixes for packaging: $pkg_ignore_suffixes"
fi

[[ -z "$pkg_desc" ]] &&
	pkg_desc="Default short description for $pkg_name" &&
	logwarn "Defaulting short package description to:" &&
	logwarn "\"$pkg_desc\""

[[ -z "$pkg_ldesc" ]] &&
	pkg_ldesc="Default long description for $pkg_name" &&
	logwarn "Defaulting long package description to:" &&
	logwarn "\"$pkg_ldesc\""

if [[ -n "$pkg_name" && "$CFGFILE" != cfg ]]
then
	logmsg "Building package: $pkg_name"
else
	pkg_name=$project_name
fi

logmsg "Project source tree named as: $project_name"

#########################################################################
# We now see if we can called the tppkg routine to handle the		#
# packaging - we expect it to be installed in /usr/local/bin/tppkg,	#
# /usr/bin/tppkg or /usr/local/tarp/bin/tppkg or TPPKG			#
#########################################################################

exec 3>autopackage/default.apspec

# Create the top of the apspec file...

print -u3 "[Meta]"
print -u3 "RootName: @$pkg_url:\$SOFTWAREVERSION"
print -u3 "ShortName: $pkg_name"
print -u3 "SoftwareVersion: $RELEASE"
print -u3 "DisplayName: $pkg_desc"
print -u3 "Summary: $pkg_ldesc"
print -u3 "Maintainer: $(whoami)"
print -u3 "Packager: $(whoami)"
print -u3 "AutopackageTarget: 1.0"
print -u3 ""
print -u3 "[Description]"
print -u3 "$pkg_ldesc"
print -u3 ""

#########################################################################
# The Buildprepare is used to build the binaries so include the code	#
# to build it, or just /bin/true to suppress warnings otherwise.	#
#########################################################################

print -u3 "[BuildPrepare]"
if [[ -n "$pkg_buildscript" ]]
then
	if [[ -n "$pkg_buildscript" ]]
	then
		print -u3 "cd $PROJECT_PREFIX/$project_name/$(dirname $pkg_buildscript)"
		print -u3 "$(cat $PROJECT_PREFIX/$project_name/$pkg_buildscript)"
	fi
        # if [[ -s $ignore_file ]]
        # then
        #        cat $ignore_file >&3
        # fi
else
	print -u3 "/bin/true"
fi

#########################################################################
# The BuildUnprepare is not really used since we are building in a	#
# temporary copy of the source tree which gets removed after package	#
# creation anyway...							#
#########################################################################

print -u3 ""
print -u3 "[BuildUnprepare]"
print -u3 "/bin/true"
print -u3 ""

#########################################################################
# The import section generates a list of files to install, using	#
# the import command for each directory of files.. However all the	#
# files need to be in $build_root, so firstly copy everything there ...	#
# and give the import list...						#
#########################################################################

print -u3 "[Imports]"
print -u3 "cd $PWD"
print -u3 "cp -Rp * \$build_root"
print -u3 "cd \$build_root"

logmsg "Building package import list ..."
predir=""
predestdir=""
loadvar $PROJECT_PREFIX/$project_name DIR: |
while read dir dest
do
	integer ctfiles=0
        dir=$(print $dir|awk -v FS=: '{print $2}')
	[[ -f  $PROJECT_PREFIX/$project_name/$dir/.ignore ]] && {
		logmsg "Ignoring directory $dir";
		continue;
	}
	#################################################################
	# Now check if extended DIR:ddd(file)... syntax has been	#
	# used...							#
	#################################################################

	pickfiles=$(print $dir|
		awk '{s1=index($0,"("); s2=index($0,")");
			if(s1>0 && s2>0) {
				print substr($0,s1+1,s2-s1-1);
			}
		     }')

	[[ -z "$pickfiles" ]] && pattern="*"
	[[ -n "$pickfiles" ]] && pattern=$(print "$pickfiles" | tr ',' ' ')
	mycd=$PWD

	#################################################################
	# Chop of the filtered files bit from the directory name	#
	# if required.							#
	#################################################################

	[[ -n "$pickfiles" ]] && {
		dir=$(print $dir|
			awk '{s1=index($0,"("); print substr($0,1,s1-1);}');
	}

	cd $PROJECT_PREFIX/$project_name/$dir 2>/dev/null || {
		logwarn "Directory \"$dir\" does not exist - ignoring.";
		continue;
	}

	#################################################################
	# Because of the extended attribute the "DIR:" might be used	#
	# multiple times for the same directory - if so, only repear	#
	# the "directory" line if similar lines are grouped.		#
	#################################################################

	predir=$dir
	predestdir=$destdir

	#################################################################
	# Now dump all the files in this directory...			#
	#################################################################

	myflist=""

	for cfile in $(eval ls -d '$pattern' 2>/dev/null)
	do
		[[ ! -f $cfile ]] && continue
		#########################################################
		# Ignore "ignore files...				#
		#########################################################

		myext="$(print $cfile|awk -v FS="." 'NF>1 {print $NF}')"
		[[ "$myext" = "ignore" ]] && continue

		if [[ -f "$cfile.ignore" ]]
		then
			continue
		fi
		
		#################################################
		# Here we check to see if the suffix matches	#
		# one of those in the pkg_ignore_suffixes list.	#
		#################################################

		if [[ -n "$pkg_ignore_suffixes" ]]
		then
			myignore=0
			mysuff=".${cfile##*.}"
			for suffix in $pkg_ignore_suffixes
			do
				if [[ "$suffix" = "$mysuff" ]]
				then
					myignore=1
					break
				fi
			done
			if [[ $myignore -eq 1 ]]
			then
				logmsg "Excluding \"$dir/$cfile\" from package build."
				continue
			fi
		fi
		myflist="$dir/$cfile $myflist"
	done
	[[ -n "$myflist" ]] && print -u3 "echo $myflist | import $dir"
	cd $mycd
done

#########################################################################
# Normally now the Prepare section would be given, but in this first	#
# iteration, dependencies are not yet supported.			#
#########################################################################

print -u3 ""
print -u3 "[Prepare]"
print -u3 "/bin/true"
print -u3 ""

#########################################################################
# Now the [Install] section. We attempt to do the following, depending	#
# on directory name elements.						#
# bin	 - installExe							#
# man	 - installMan							#
# lib    - installLib							#
# share	 - installData							#
#									#
# If no type is matched use the copyFile option.			#
#########################################################################

logmsg "Building package install list..."
print -u3 "[Install]"
predir=""
predestdir=""
loadvar $PROJECT_PREFIX/$project_name DIR: |
while read dir dest
do
	integer ctfiles=0
        dir=$(print $dir|awk -v FS=: '{print $2}')
	[[ -f  $PROJECT_PREFIX/$project_name/$dir/.ignore ]] && {
		logmsg "Ignoring directory $dir";
		continue;
	}

	#################################################################
	# Attempt to determine the type of file from the directory	#
	# name...							#
	#################################################################

	ftype=$(print "$dir" | awk '/bin/ {print "installExe";exit;}
				/man/ {print "installMan";exit;}
				/lib/ {print "installLib";exit;}
				/share/ {print "installData"; exit;}
				{print "copyFile";exit;}')

	#################################################################
	# Get the user, group and permissions, if specified		#
	#################################################################

	user=$(print $dest|awk -v FS=, '{print $2}')
	user=${user:-root}
	group=$(print $dest|awk -v FS=, '{print $3}')
	group=${group:-root}
	perms=$(print $dest|awk -v FS=, '{print $4}')
	perms=${perms:-750}
	destdir=$(print $dest|awk -v FS=, '{print $1}')

	#################################################################
	# Now check if extended DIR:ddd(file)... syntax has been	#
	# used...							#
	#################################################################

	pickfiles=$(print $dir|
		awk '{s1=index($0,"("); s2=index($0,")");
			if(s1>0 && s2>0) {
				print substr($0,s1+1,s2-s1-1);
			}
		     }')

	[[ -z "$pickfiles" ]] && pattern="*"
	[[ -n "$pickfiles" ]] && pattern=$(print "$pickfiles" | tr ',' ' ')

	mycd=$PWD

	#################################################################
	# Chop of the filtered files bit from the directory name	#
	# if required.							#
	#################################################################

	[[ -n "$pickfiles" ]] && {
		dir=$(print $dir|
			awk '{s1=index($0,"("); print substr($0,1,s1-1);}');
	}

	cd $PROJECT_PREFIX/$project_name/$dir 2>/dev/null || {
		logwarn "Directory \"$dir\" does not exist - ignoring.";
		continue;
	}

	#################################################################
	# Because of the extended attribute the "DIR:" might be used	#
	# multiple times for the same directory - if so, only repear	#
	# the "directory" line if similar lines are grouped.		#
	#################################################################

	predir=$dir
	predestdir=$destdir

	#################################################################
	# Now dump all the files in this directory...			#
	#################################################################

	myflist=""
	for cfile in $(eval ls -d "$pattern" 2>/dev/null)
	do
		[[ ! -f $cfile ]] && continue
		#########################################################
		# Ignore "ignore files...				#
		#########################################################

		myext="$(print $cfile|awk -v FS="." 'NF>1 {print $NF}')"
		[[ "$myext" = "ignore" ]] && continue

		if [[ -f "$cfile.ignore" ]]
		then
			continue
		fi
		
		#################################################
		# Here we check to see if the suffix matches	#
		# one of those in the pkg_ignore_suffixes list.	#
		#################################################

		if [[ -n "$pkg_ignore_suffixes" ]]
		then
			myignore=0
			mysuff=".${cfile##*.}"
			for suffix in $pkg_ignore_suffixes
			do
				if [[ "$suffix" = "$mysuff" ]]
				then
					myignore=1
					break
				fi
			done
			if [[ $myignore -eq 1 ]]
			then
				logmsg "Excluding \"$dir/$cfile\" from package build."
				continue
			fi
		fi
		if [[ "$pkg_relative" = "YES" ]]
		then
			print -u3 "$ftype $cfile"
			print -u3 "chown $user:$group \$PREFIX/$dir/$cfile"
			print -u3 "chmod $perms \$PREFIX/$dir/$cfile"
		else
			print -u3 "if [ ! -d $destdir ] ; then mkdir -p $destdir; fi"
			print -u3 "copyFile --silent $dir/$cfile $destdir/$cfile"
			print -u3 "chown $user:$group $destdir/$cfile"
			print -u3 "chmod $perms $destdir/$cfile"
		fi
	done
	cd $mycd
done

#########################################################################
# After installing the files, we also need to run a post-install, if	#
# it is available in this configuration.				#
#########################################################################

if [[ -n "$pkg_postinstall" && -f "$pkg_postinstall" ]]
then
	print -u3 "set +e"
	print -u3 "exec >~/postinstall-$project_name.stdout\nexec 2>~/postinstall-$project_name.stderr\n$(<$pkg_postinstall)\n"
fi

print -u3 ""
print -u3 "[Uninstall]"
print -u3 "uninstallFromLog"
if [[ -n "$pkg_postremove" && -f "$pkg_postremove" ]]
then
	print -u3 ""
	  print -u3 "exec >~/postremove-$project_name.stdout\nexec 2>~/postremove-$project_name.stderr\n$(<$pkg_postremove)\n"
	cat $pkg_postremove >&3
fi

#########################################################################
# The spec file has been created so now actually create package!	#
#########################################################################
cp autopackage/default.apspec /tmp/xxxx

makeinstaller | tee /tmp/mkpkg.2.$$

file=$(tail -5 /tmp/mkpkg.2.$$ | awk '/The complete package is/ {print substr($NF,2,length($NF)-3)}')
print "file=$file"
if [[ -z "$file" || ! -f "$file" ]]
then
	file=$(tail -1 /tmp/mkpkg.2.$$ | awk '{print $NF}')
fi
[[ -z "$file" || ! -f "$file" ]] && logerr "Failed to create Autopackage." 23

if [[ -n "$FINAL_DEPOT" && "$FINAL_DEPOT" != "$pkg_depot" ]]
then
	cp $file $FINAL_DEPOT 2>/dev/null
	if [[ $? -eq 0 ]]
	then
		logmsg "Copied package $file to depot $FINAL_DEPOT successfully."
	else
		logerr "Unable to copy $file to depot $FINAL_DEPOT." 22
	fi
fi
exit 0

